package com.neusoft.hifly.core.token.filter;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;
import java.util.Objects;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.alibaba.fastjson.JSON;
import com.auth0.jwt.interfaces.Claim;
import com.neusoft.hifly.core.log.Log;
import com.neusoft.hifly.core.pojo.ApiCode;
import com.neusoft.hifly.core.pojo.ApiResponse;
import com.neusoft.hifly.core.redis.RedisCache;
import com.neusoft.hifly.core.token.JwtUtil;
import com.neusoft.hifly.core.token.TokenContextHolder;
import com.neusoft.hifly.core.token.domain.TokenVO;
import com.neusoft.hifly.security.EncodeUtils;

/**
 * 拦截除了登录外的请求
 */
@Component
public class JwtInterceptor implements HandlerInterceptor {

	@Autowired(required = false)
	private RedisCache redisCache;

	private void output(final ApiResponse<?> jsonData, final HttpServletResponse response) throws IOException {
		response.setContentType("text/html;charset=UTF-8;");
		final PrintWriter out = response.getWriter();
		out.write(Objects.requireNonNull(JSON.toJSONString(jsonData)));
		out.flush();
		out.close();
	}

	/**
	 * 在服务请求执行前执行，它负责析取请求header中的orgCode(机构码)，并把它塞入ThreadLocal全局变量中
	 */
	@Override
	public boolean preHandle(final HttpServletRequest request, final HttpServletResponse response, final Object handler)
			throws Exception {
		// 前段ajax自定义headers字段，会出现了option请求，在GET请求之前。
		// 所以应该把他过滤掉，以免影响服务。但是不能返回false，如果返回false会导致后续请求不会继续。
		if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
			return true;
		}
		// 从请求头中获取token
		final String token = request.getHeader(JwtUtil.TOKEN_KEY);
		// 去redis里面获取公钥
		final String secret = redisCache.get(EncodeUtils.md5Encode(token));

		final Map<String, Claim> resultMap = JwtUtil.getByKey(secret, token);
		if (resultMap == null || resultMap.isEmpty()) {
			Log.warn("无效token：" + token);
			// JsonData是返回给前端的json格式(不重要)
			output(new ApiResponse<>(ApiCode.TOKEN_EXPIRED.getCode(), "您的token不合法或已经过期！"), response);
			return false;
		}

		final TokenVO tokenVO = new TokenVO();
		tokenVO.setToken(token);

		if (resultMap.containsKey(JwtUtil.USER_ID)) {
			tokenVO.setUserId(resultMap.get(JwtUtil.USER_ID).asString());
		}
		if (resultMap.containsKey(JwtUtil.LOGIN_NAME)) {
			tokenVO.setLoginName(resultMap.get(JwtUtil.LOGIN_NAME).asString());
		}
		if (resultMap.containsKey(JwtUtil.USER_NAME)) {
			tokenVO.setUserName(resultMap.get(JwtUtil.USER_NAME).asString());
		}
		if (resultMap.containsKey(JwtUtil.HOSPITALS)) {
			tokenVO.setHospitals(resultMap.get(JwtUtil.HOSPITALS).asString());
		}
		if (resultMap.containsKey(JwtUtil.DEPARTMENTS)) {
			tokenVO.setDepartments(resultMap.get(JwtUtil.DEPARTMENTS).asString());
		}
		if (resultMap.containsKey(JwtUtil.REGIONS)) {
			tokenVO.setRegions(resultMap.get(JwtUtil.REGIONS).asString());
		}

		// 记录Token
		TokenContextHolder.set(tokenVO);
		return true;
	}

	@Override
	public void afterCompletion(final HttpServletRequest request, final HttpServletResponse response, final Object o,
			final Exception e) throws Exception {

	}

	/**
	 * 负责在服务请求执行后（就算服务抛出异常也会被执行），主要是清除ThreadLocal全局变量中的内容，为下一个请求到来做准备
	 */
	@Override
	public void postHandle(final HttpServletRequest request, final HttpServletResponse response, final Object o,
			final ModelAndView modelAndView) throws Exception {
		//		OrganCodeContextHolder.clear();
	}

}